package traingo

import (
	"context"
	"errors"
	"github.com/chromedp/cdproto/network"
	"github.com/chromedp/cdproto/target"
	"github.com/chromedp/chromedp"
	"github.com/sirupsen/logrus"
	"net/http"
	"net/http/httptest"
	"strings"
)

type TraingoStudy struct {
	urlPrefix    string
	apiPrefix    string
	username     string
	pwd          string
	token        string
	ctx          context.Context
	cancel       context.CancelFunc
	newCtx       context.Context
	remoteLoginC chan int
}

func New(headless bool) *TraingoStudy {
	obj := &TraingoStudy{
		urlPrefix:    "https://gms-test.traingo.com.cn",
		apiPrefix:    "https://api.test.tgtrain.cn",
		username:     "hechongyang",
		pwd:          "12345678",
		remoteLoginC: make(chan int, 1),
	}
	options := []chromedp.ExecAllocatorOption{
		chromedp.Flag("headless", headless), // 是否打开浏览器调试
		chromedp.UserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"), // 设置User-Agent
	}
	options = append(chromedp.DefaultExecAllocatorOptions[:], options...)
	// chromdp依赖context上限传递参数
	obj.ctx, obj.cancel = chromedp.NewExecAllocator(
		context.Background(),
		options...,
	)
	obj.ctx, obj.cancel = chromedp.NewContext(
		obj.ctx,
	)
	return obj
}

func (s *TraingoStudy) Run() error {
	return chromedp.Run(s.ctx, chromedp.Tasks{
		s.MyFuncListenTarget(),
		//s.MyFuncRegisterNewTarget(),
		chromedp.Navigate(s.urlPrefix),
		s.userLogin(),
		chromedp.Click(`document.getElementsByClassName("ant-btn ant-btn-primary ant-btn-background-ghost mx-2")[0]`, chromedp.ByJSPath),
		s.MyFuncListenQuit(),
	})
}

func (s *TraingoStudy) MyFuncListenTarget() chromedp.Action {
	return chromedp.ActionFunc(func(ctx context.Context) error {
		mux := http.NewServeMux()
		ts := httptest.NewServer(mux)
		defer ts.Close()
		chromedp.ListenTarget(s.ctx, func(ev interface{}) {
			switch e := ev.(type) {
			case *network.EventResponseReceived:
				go func() {
					switch e.Type {
					case network.ResourceTypeDocument:
						logrus.Debug("打开页面：", e.Response.URL)
					case network.ResourceTypeXHR:
						s.ajaxCheck(e)
					case network.ResourceTypeWebSocket:
						logrus.Debug("websocket：", e.Response.URL)
					case network.ResourceTypeFetch:
						logrus.Debug("请求 fetch 接口：", e.Response.URL)
					default:
						//	logrus.Debug("暂时用不到的其他类型请求：", e.RequestID.String())
					}
				}()
			}
		})
		return nil
	})
}

func (s *TraingoStudy) MyFuncRegisterNewTarget() chromedp.ActionFunc {
	return func(ctx context.Context) error {
		go func() {
			mux := http.NewServeMux()
			ts := httptest.NewServer(mux)
			defer ts.Close()
			// 等待新页面打开
			ch := chromedp.WaitNewTarget(ctx, func(info *target.Info) bool {
				logrus.Debugf("打开新页面,url: %s,TargetID:%s", info.URL, info.TargetID)
				return info.URL != ""
			})
			// 将新开页面设置到上下文中
			s.newCtx, s.cancel = chromedp.NewContext(ctx, chromedp.WithTargetID(<-ch))
			chromedp.Run(s.newCtx,
				chromedp.WaitVisible(`#app`, chromedp.ByID),
				chromedp.ActionFunc(func(ctx context.Context) error {
					chromedp.ListenTarget(ctx, func(ev interface{}) {
						switch e := ev.(type) {
						case *network.EventResponseReceived:
							go func() {
								switch e.Type {
								case network.ResourceTypeDocument:
									logrus.Debug("222 document：", e.Response.URL)
									//s.docCheck(e)
								case network.ResourceTypeXHR:
									logrus.Debug("222 ajax：", e.Response.URL)
									s.ajaxCheck(e)
								case network.ResourceTypeWebSocket:
									logrus.Debug("websocket：", e.Response.URL)
								case network.ResourceTypeFetch:
									logrus.Debug("请求 fetch 接口：", e.Response.URL)
								default:
									//	logrus.Debug("暂时用不到的其他类型请求：", e.RequestID.String())
								}
							}()
						}
					})
					return nil
				}),
			)
		}()
		return nil
	}
}

func (s *TraingoStudy) ajaxCheck(e *network.EventResponseReceived) {
	url := e.Response.URL[len(s.apiPrefix):]
	if !strings.HasPrefix(url, "/") {
		url = "/" + url
	}
	switch e.Response.URL[len(s.apiPrefix):] {
	case "/study/accountLogin":
		s.loginAjax(e)
	default:
		//logrus.Debug("还未处理的接口")
	}
}

func (s *TraingoStudy) MyFuncListenQuit() chromedp.ActionFunc {
	return func(ctx context.Context) error {
		for {
			select {
			case <-s.ctx.Done():
				logrus.Info("浏览器被关闭，退出进程")
				return errors.New("浏览器被关闭，退出进程")
			default:
			}
		}
	}
}
